package com.gs.es.utils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.gs.common.tool.consts.AttributeConst;
import com.gs.common.tool.pojo.ColumnInfo;
import com.gs.common.tool.utils.CollectionUtil;
import com.gs.common.tool.utils.PoJoUtil;
import com.gs.common.tool.utils.StringUtil;
import com.gs.common.tool.utils.XmlUtil;
import com.gs.es.consts.TagConst;
import com.gs.es.model.TableTagInfo;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * java文件生成工具
 *
 * @author: guos
 * @date: 2024/09/03 11:57
 **/
public class GenerateJavaUtil {


    /**
     * 生成java类
     *
     * @param configFilePath 配置文件路径
     * @date 2024/09/03 12:00
     **/
    public static List<String> generate(String configFilePath, String indexFieldInfoStr) throws DocumentException {
        List<String> errorList = Lists.newArrayList();
        //解析配置文件
        Document document = new SAXReader().read(new File(configFilePath));
        Element context = document.getRootElement().element(TagConst.context);
        if (Objects.isNull(context)) {
            errorList.add(String.format("%s element tag is not null!%n", TagConst.context));
            return errorList;
        }
        List<Element> elements = context.elements();
        if (CollectionUtil.isEmpty(elements)) {
            errorList.add(String.format("%s element tag must have child!", TagConst.context));
            return errorList;
        }
        Map<String, Element> elementMap = elements.stream().collect(Collectors.toMap(Element::getName, Function.identity(), (k1, k2) -> k2));
        Element author = elementMap.get(TagConst.author);
        Element baseInfo = elementMap.get(TagConst.baseInfo);
        Element entity = elementMap.get(TagConst.entity);
        Element service = elementMap.get(TagConst.service);
        Element serviceImpl = elementMap.get(TagConst.serviceImpl);
        Element controller = elementMap.get(TagConst.controller);
        Element tables = elementMap.get(TagConst.indexes);
        //es相关注解
        Element annotations = elementMap.get(TagConst.annotations);
        if (Objects.isNull(baseInfo)) {
            errorList.add(String.format("%s element is not null!", TagConst.annotations));
            return errorList;
        }
        Map<String, String> esAnnoMap = Maps.newHashMap();
        if (Objects.nonNull(annotations)) {
            annotations.elements().forEach(a -> {
                String attributeValue = XmlUtil.getAttributeValue(a, AttributeConst.annotationValue);
                if (StringUtil.isNotEmpty(attributeValue)) {
                    esAnnoMap.put(XmlUtil.getAttributeValue(a, AttributeConst.annotationName), attributeValue);
                }
            });
        }
        String authorName = XmlUtil.getAttributeValue(author.attribute(AttributeConst.value));
        String basePathName = XmlUtil.getAttributeValue(baseInfo, AttributeConst.path);
        String basePackageName = XmlUtil.getAttributeValue(baseInfo, AttributeConst.pack);
        String entityPathName = XmlUtil.getPath(basePathName, entity);
        String entityPackageName = XmlUtil.getPackage(basePackageName, entity);
        //String entityAnnotation = XmlUtil.getAttributeValue(entity, AttributeConst.annotation);
        String entitySuperClass = XmlUtil.getAttributeValue(entity, AttributeConst.superClass);

        String servicePathName = XmlUtil.getPath(basePathName, service);
        String servicePackageName = XmlUtil.getPackage(basePackageName, service);
        String serviceSuffix = PoJoUtil.firstToUpper(XmlUtil.getAttributeValue(service.attribute(AttributeConst.suffix)));
        String serviceSuperClass = XmlUtil.getAttributeValue(service, AttributeConst.superClass);

        String serviceImpPathName = XmlUtil.getPath(basePathName, serviceImpl);
        String serviceImplPackageName = XmlUtil.getPackage(basePackageName, serviceImpl);
        String serviceImplSuffix = PoJoUtil.firstToUpper(XmlUtil.getAttributeValue(serviceImpl.attribute(AttributeConst.suffix)));
        String serviceImplSuperClass = XmlUtil.getAttributeValue(serviceImpl, AttributeConst.superClass);

        String controllerPathName = XmlUtil.getPath(basePathName, controller);
        String controllerPackageName = XmlUtil.getPackage(basePackageName, controller);
        String controllerSuffix = PoJoUtil.firstToUpper(XmlUtil.getAttributeValue(controller.attribute(AttributeConst.suffix)));
        String controllerSuperClass = XmlUtil.getAttributeValue(controller, AttributeConst.superClass);
        //解析表结构文件
        AtomicInteger index = new AtomicInteger(0);
        List<ColumnInfo> columnInfoList = Arrays.stream(indexFieldInfoStr.split("\r\n")).filter(StringUtil::isNotEmpty).map(l -> {
            ColumnInfo columnInfo = new ColumnInfo();
            String[] columns = l.split("\\|\\|");
            columnInfo.setIndex(index.getAndIncrement())
                    .setTableName(columns[0].trim()).setColumnName(columns[1].trim()).setColumnType(columns[2].trim());
            if (columns.length > 3) {
                columnInfo.setColumnComment(columns[3]);
            }
            return columnInfo;
        }).collect(Collectors.toList());
        //根据表名分组
        Map<String, List<ColumnInfo>> tableColumnMap = columnInfoList.stream().collect(Collectors.groupingBy(ColumnInfo::getTableName));
        //遍历表
        tables.elements().forEach(t -> {
            String tableName = XmlUtil.getAttributeValue(t.attribute(TableTagInfo.Fields.name));
            String tableComment = XmlUtil.getAttributeValue(t.attribute(com.gs.common.tool.pojo.TableTagInfo.Fields.comment));
            String pojoPrefix = XmlUtil.getAttributeValue(t.attribute(com.gs.common.tool.pojo.TableTagInfo.Fields.pojoPrefix));
            String genPojo = XmlUtil.getAttributeValue(t.attribute(com.gs.common.tool.pojo.TableTagInfo.Fields.genPojo));
            String genService = XmlUtil.getAttributeValue(t.attribute(com.gs.common.tool.pojo.TableTagInfo.Fields.genService));
            String genServiceImpl = XmlUtil.getAttributeValue(t.attribute(com.gs.common.tool.pojo.TableTagInfo.Fields.genServiceImpl));
            String genController = XmlUtil.getAttributeValue(t.attribute(com.gs.common.tool.pojo.TableTagInfo.Fields.genController));
            String enableSuper = XmlUtil.getAttributeValue(t.attribute(com.gs.common.tool.pojo.TableTagInfo.Fields.enableSuper));

            List<ColumnInfo> tableColumnInfoList = tableColumnMap.get(tableName);
            if (CollectionUtil.isEmpty(tableColumnInfoList)) {
                errorList.add(String.format("index 【%s】属性信息解析失败!", tableName));
                return;
            }
            //按照列索引升序
            tableColumnInfoList.sort(Comparator.comparing(ColumnInfo::getIndex));
            //实体类名
            String pojoName = PoJoUtil.getEntityName(pojoPrefix, tableName, XmlUtil.getAttributeValue(t.attribute(com.gs.common.tool.pojo.TableTagInfo.Fields.pojoName)));
            //生成实体类
            if (XmlUtil.isTrue(genPojo)) {
                JavaCodeGenUtil.genPojo(entityPathName, esAnnoMap, tableName, pojoName, entityPackageName, enableSuper, XmlUtil.getAttributeValue(entity.attribute(AttributeConst.enableSuper)), entitySuperClass, tableComment, tableColumnInfoList, authorName);
            }
            String entityFullName = String.format("%s.%s", entityPackageName, pojoName);
            String serviceFullName = String.format("%s.I%s%s", servicePackageName, pojoName, serviceSuffix);
            //生成service
            if (XmlUtil.isTrue(genService)) {
                JavaCodeGenUtil.genService(servicePathName, entityFullName, servicePackageName, serviceSuffix, enableSuper, XmlUtil.getAttributeValue(service.attribute(AttributeConst.enableSuper)), serviceSuperClass, tableComment, authorName);
            }
            //生成serviceImpl
            if (XmlUtil.isTrue(genServiceImpl)) {
                JavaCodeGenUtil.genServiceImpl(serviceImpPathName, entityFullName, serviceFullName, serviceImplPackageName, serviceImplSuffix, enableSuper, XmlUtil.getAttributeValue(serviceImpl.attribute(AttributeConst.enableSuper)), serviceImplSuperClass, tableComment, authorName);
            }
            //生成controller
            if (XmlUtil.isTrue(genController)) {
                JavaCodeGenUtil.genController(controllerPathName, entityFullName, serviceFullName, controllerPackageName, controllerSuffix, enableSuper, XmlUtil.getAttributeValue(controller.attribute(AttributeConst.enableSuper)), controllerSuperClass, tableComment, authorName);
            }
            errorList.add(String.format("index-->【%s】 generate successful !%n", tableName));
        });
        return errorList;
    }
}
